package com.example.my_bookkeeping;

import static androidx.test.espresso.Espresso.onData;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.anything;
import static org.hamcrest.Matchers.is;

import static java.lang.Thread.sleep;

import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.test.espresso.DataInteraction;
import androidx.test.espresso.ViewInteraction;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;

import com.example.my_bookkeeping.data.manager.UserManager;
import com.example.my_bookkeeping.data.user.User;
import com.example.my_bookkeeping.ui.account.AccountFragment;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class DeleteUserTest {

    @Rule
    public ActivityScenarioRule<MainActivity> mActivityScenarioRule =
            new ActivityScenarioRule<>(MainActivity.class);
    private UserManager userManager;

    @Before
    public void setUp() {
        userManager = UserManager.getInstance();
        userManager.reset();
        userManager.add(new User("testUser1", "testUser", 0));
        userManager.add(new User("testUser2", "testUser", 0));
    }

    @After
    public void tearDown() {
        userManager.reset();
    }

    @Test
    public void deleteUserTest() throws InterruptedException {
        ViewInteraction bottomNavigationItemView = onView(
                allOf(withId(R.id.item_account), withContentDescription("我的账户"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.bottom_navigation_view),
                                        0),
                                4),
                        isDisplayed()));
        bottomNavigationItemView.perform(click());

        sleep(1000);

        ViewInteraction appCompatSpinner = onView(
                allOf(withId(R.id.spinner_account),
                        childAtPosition(
                                allOf(withId(R.id.userListCard),
                                        childAtPosition(
                                                withClassName(is("androidx.constraintlayout.widget.ConstraintLayout")),
                                                1)),
                                0),
                        isDisplayed()));
        appCompatSpinner.perform(click());

        DataInteraction appCompatCheckedTextView = onData(anything())
                .inAdapterView(childAtPosition(
                        withClassName(is("android.widget.PopupWindow$PopupBackgroundView")),
                        0))
                .atPosition(1);
        appCompatCheckedTextView.perform(click());

        ViewInteraction appCompatButton = onView(
                allOf(withId(R.id.btn_delete_account), withText("删除账户"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.modifyUserCard),
                                        0),
                                2),
                        isDisplayed()));
        appCompatButton.perform(click());

        ViewInteraction appCompatButton2 = onView(
                allOf(withId(android.R.id.button1), withText("确定"),
                        childAtPosition(
                                childAtPosition(
                                        withClassName(is("android.widget.ScrollView")),
                                        0),
                                3)));
        appCompatButton2.perform(scrollTo(), click());

        sleep(100);

        // 断言用户已被删除
        assert userManager.getAll().size() == 2;
        for (User user : userManager.getAll()) {
            assert !user.getName().equals("testUser1");
        }
        assert userManager.getCurrentUser().getName().equals("系统用户");

        // 当前用户视图信息已被更新
        mActivityScenarioRule.getScenario().onActivity(activity -> {
            AccountFragment fragment = (AccountFragment) activity.getSupportFragmentManager()
                    .findFragmentByTag("f" + 3);
            assert fragment != null;
            View rootView = fragment.getView();
            assert rootView!= null;
            Spinner spinnerAccount = rootView.findViewById(R.id.spinner_account);
            TextView tvAccountName = rootView.findViewById(R.id.tv_account_name);
            assert tvAccountName.getText().toString().equals("系统用户");
            String selectedItem = ((User)spinnerAccount.getSelectedItem()).getName();
            assert selectedItem.equals("系统用户");
        });
    }

    private static Matcher<View> childAtPosition(
            final Matcher<View> parentMatcher, final int position) {

        return new TypeSafeMatcher<View>() {
            @Override
            public void describeTo(Description description) {
                description.appendText("Child at position " + position + " in parent ");
                parentMatcher.describeTo(description);
            }

            @Override
            public boolean matchesSafely(View view) {
                ViewParent parent = view.getParent();
                return parent instanceof ViewGroup && parentMatcher.matches(parent)
                        && view.equals(((ViewGroup) parent).getChildAt(position));
            }
        };
    }
}
